<template>
    <div class="carousel" ref="carousel-box">
        <div class="carousel-content">
            <slot></slot>
        </div>
        <div class="carousel-prev" @click.stop="prev"><</div>
        <div class="carousel-next" @click.stop="next">></div>
        <div class="carousel-pagination"></div>
    </div>
</template>

<script>
    export default {
        name: 'Carousel',
        data () {
            return {
                isMove: false,
                startX: 0,
                startY: 0,
                index: 0,
                maxIndex: 0,
                timeout: null
            };
        },
        props: {
            loop: {type: Boolean, default: false},
            loopTime: {type: Number, default: 5000}
        },
        methods: {
            bindTouchEvent () {
                this.$el.children[0].addEventListener('mousedown', this.onTouchStart);
                document.addEventListener('mousemove', this.onTouchMove);
                document.addEventListener('mouseup', this.onTouchEnd);
            },
            onTouchStart (e) {
                this.isMove = true;
                this.startX = e.pageX;
                window.el = e;
            },
            onTouchMove (e) {
                if (this.isMove === false) return false;
                let m = e.pageX - this.startX;
                this.getEl().style.transitionDuration = '0ms';
                this.getEl().style.transform = 'translate3d(' + m + 'px,0,0)';
            },
            onTouchEnd () {
                this.isMove = false;
                this.getEl().style.transitionDuration = '300ms';
                this.getEl().style.transform = 'translate3d(0 , 0, 0)';
            },
            getEl () {
                return this.$el.children[0];
            },
            init () {
                this.bindTouchEvent();
                this.computePagination();
                this.bindButton();
                this.addDefaultClass();
                this.setLoop();
            },
            computePagination () {
                let list = this.getEl();
                let count = list.childElementCount;
                let pagination = this.$el.getElementsByClassName('carousel-pagination')[0];
                if (pagination && pagination.length) {
                    return;
                }
                let html = '';
                let w = this.$el.offsetWidth;
                for (let i = 0; i < count; i++) {
                    html = `${html}<a data-index="${i}"></a>`;
                    let mw = 0;
                    for (let x = i; x < count; x++) {
                        mw += list.children[x].offsetWidth + 30;
                    }
                    if (mw < w) {
                        this.maxIndex = i + 1;
                        break;
                    } else {
                        this.maxIndex = count;
                    }
                }
                pagination.innerHTML = html;
            },
            prev () {
                this.index--;
                if (this.index < 0) {
                    this.index = this.maxIndex - 1;
                }
                this.switchPage(this.index);
            },
            next () {
                this.index++;
                if (this.index >= this.maxIndex) {
                    this.index = 0;
                }
                this.switchPage(this.index);
            },
            bindButton () {
                this.$el.getElementsByClassName('carousel-pagination')[0].addEventListener('click', this.changePage);
            },
            changePage (e) {
                this.switchPage(e.srcElement.getAttribute('data-index'));
            },
            switchPage (index) {
                if (index >= this.maxIndex) return false;
                let content = this.getEl();

                let w = 0;

                for (let i = 0; i < index; i++) {
                    w = w + content.children[i].offsetWidth + 30;
                }

                if (index === 0) {
                    w = 0;
                }

                this.removeActive();
                this.$el.querySelector('.carousel-pagination > a[data-index="' + index + '"]').className = 'active';
                this.getEl().style.transitionDuration = '300ms';
                this.getEl().style.transform = 'translate3d(-' + w + 'px , 0, 0)';
                this.index = index;
                this.setLoop();
            },
            removeActive () {
                let list = this.$el.querySelectorAll('.carousel-pagination > a');
                if ((list && list.length) === false) return;
                for (let index in list) {
                    if (index >= 0) {
                        list[index].className = '';
                    }
                }
            },
            addDefaultClass () {
                this.$nextTick(() => {
                    let el = this.$el.querySelector('.carousel-pagination > a[data-index="0"]');
                    if (el !== null) {
                        el.className = 'active';
                    }
                });
            },
            update () {
                this.unBind();
                this.init();
            },
            unBind () {
                this.$el.children[0].removeEventListener('mousedown', this.onTouchStart);
                document.removeEventListener('mousemove', this.onTouchMove);
                document.removeEventListener('mouseup', this.onTouchEnd);
                this.$el.getElementsByClassName('carousel-pagination')[0].removeEventListener('click', this.changePage);
            },
            setLoop () {
                this.clearTime();
                if (this.loop === true) {
                    this.timeout = setInterval(() => {
                        this.next();
                    }, this.loopTime);
                }
            },
            clearTime () {
                if (this.timeout !== null) {
                    clearInterval(this.timeout);
                    this.timeout = null;
                }
            }
        },
        mounted () {
            this.init();
        }
    };
</script>

<style>
    .carousel {
        margin-left: auto;
        margin-right: auto;
        position: relative;
        overflow: hidden;
        z-index: 1;
    }

    .carousel-content {
        position: relative;
        width: auto;
        height: auto;
        display: flex;
        cursor: pointer;
    }

    .carousel-next, .carousel-prev {
        background-color: rgba(0, 0, 0, .5);
        position: absolute;
        width: 50px;
        height: 50px;
        line-height: 50px;
        top: 50%;
        margin-top: -25px;
        cursor: pointer;
        text-align: center;
        color: white;
        font-size: 30px;
        font-family: "Segoe UI", serif;
    }

    .carousel-prev {
        left: 0;
    }

    .carousel-next {
        right: 0;
    }

    .carousel-pagination {
        height: auto;
        width: 100%;
        position: absolute;
        bottom: 10px;
        left: 0;
        text-align: center;
    }

    .carousel-pagination > a {
        display: inline-block;
        width: 15px;
        height: 15px;
        background-color: white;
        margin: 0 3px;
        border-radius: 50%;
        cursor: pointer;
        border: 1px solid #737373;
    }

    .carousel-pagination > a.active {
        background-color: #737373;
    }
</style>
